
#include <sys/types.h>

#define RK_LIL_ENDIAN 1

#ifndef ETHER_ADDR_LEN
#define ETHER_ADDR_LEN 6
#endif 

#ifndef ETHER_CRC_LEN
#define ETHER_CRC_LEN 4
#endif 


#ifndef __PKT_HEADER_H__
#define __PKT_HEADER_H__




typedef struct rook_ether_h   EthHdr;   /* Ethernet */
typedef struct rook_lcc_h     LccHdr;   /* Linux cooked capture */
typedef struct rook_arp_h     ArpHdr;   /* Arp */
typedef struct rook_dot1q_h   Dot1qHdr; /* VLAN (802.11q) */
typedef struct rook_ipv4_h    IPv4Hdr;  
typedef struct rook_ipv6_h    IPv6Hdr;
typedef struct rook_tcp_h     TcpHdr;
typedef struct rook_udp_h     UdpHdr;
typedef struct rook_icmpv6_h  Icmp6Hdr;
typedef struct rook_icmpv4_h  Icmp4Hdr;
typedef struct rook_icmpv4_d  Icmp4Data;
typedef struct rook_dns_h     DnsHdr;
typedef struct rook_dns_rr_h  DnsRRHdr;
typedef struct rook_netbios_h NetbiosHdr;
typedef struct rook_dcerpc_h  DcerpcHdr;
typedef struct rook_ssl_h     SslHdr;
typedef struct rook_tftp_h    TftpHdr;
typedef struct rook_template TemplateHdr;

#ifndef ETHERTYPE_ARP
#define ETHERTYPE_ARP 0x0806
#endif
#ifndef ETHERTYPE_VLAN
#define ETHERTYPE_VLAN 0x8100
#endif
#ifndef ETHERTYPE_IP
#define ETHERTYPE_IP 0x0800
#endif
#ifndef ETHERTYPE_IPV6
#define ETHERTYPE_IPV6 0x86dd
#endif
#ifndef ETHERTYPE_LOOPBACK
#define ETHERTYPE_LOOPBACK 0x9000
#endif
#ifndef ETHERTYPE_WLCCP /* Cisco Wireless LAN Context Control Protocol */
#define ETHERTYPE_WLCCP 0x872d
#endif
#ifndef ETHERTYPE_NETWARE /* Netware IPX/SPX */
#define ETHERTYPE_NETWARE 0x8137
#endif

struct rook_ether_h
{
  u_int8_t etherDstHost[ETHER_ADDR_LEN];
  u_int8_t etherSrcHost[ETHER_ADDR_LEN];
  u_int16_t etherType;
};

#ifndef ETHERTYPE_802
#define ETHERTYPE_8021Q 0x8100	/* 802.1Q VLAN Extended Header  */
#endif

#ifndef VLAN_VID_MASK
#define VLAN_VID_MASK   0xfff
#endif

struct rook_lcc_h
{
  u_int16_t pktType;
  u_int16_t addrType; 
  u_int16_t addrLen;
  u_int8_t addr[8];
  u_int16_t proto;
};

struct rook_arp_h
{
  u_int16_t hwAddrFmt;
#define ARPHRD_ETHER    1       /* ethernet hardware format */
#define ARPHRD_IEEE802  6       /* token-ring hardware format */
#define ARPHRD_FRELAY   15      /* frame relay hardware format */
#define ARPHRD_IEEE1394 24      /* IEEE1394 hardware address */
#define ARPHRD_IEEE1394_EUI64 27 /* IEEE1394 EUI-64 */

  u_int16_t protoFmt;
  u_int8_t hwAddrLen;
  u_int8_t prAddrLen;

  u_int16_t op;  
#define ARPOP_REQUEST   1       /* request to resolve address */
#define ARPOP_REPLY     2       /* response to previous request */
#define ARPOP_REVREQUEST 3      /* request protocol address given hardware */
#define ARPOP_REVREPLY  4       /* response giving protocol address */
#define ARPOP_INVREQUEST 8      /* request to identify peer */
#define ARPOP_INVREPLY  9       /* response identifying peer */

};

struct rook_dot1q_h
{
  u_int16_t dot1qTCI;		/* Encapsulates priority and VLAN ID */
  u_int16_t dot1qEncapProto;	/* Encapsulated Protocol ID or Len */
};


#ifndef IPPROTO_ICMP
#define IPPROTO_ICMP   1
#endif
#ifndef IPPROTO_TCP   
#define IPPROTO_TCP    6
#endif
#ifndef IPPROTO_UDP   
#define IPPROTO_UDP   17
#endif

#ifndef IPPROTO_IPV6
#define IPPROTO_IPV6  41
#endif
#ifndef IPPROTO_ICMP6
#define IPPROTO_ICMP6 58
#endif
#ifndef IPPROTO_NONE
#define IPPROTO_NONE  59
#endif

struct rook_ipv4_h
{
#if (RK_LIL_ENDIAN)
  u_int8_t ipHL:4;
  u_int8_t ipV:4;
#endif
#if (RK_BIG_ENDIAN)
  u_int8_t ipV:4;
  u_int8_t ipHL:4;
#endif

  u_int8_t ipTos;
  u_int16_t ipTL;		/* total length */
  u_int16_t ipID;
#define IP_RF 0x8000                    /* reserved fragment flag */
#define IP_DF 0x4000                    /* dont fragment flag */
#define IP_MF 0x2000                    /* more fragments flag */
#define IP_OFFMASK 0x1fff               /* mask for fragmenting bits */
  u_int16_t ipOff;		/* fragment offset */
  u_int8_t ipTTL;		/* Time To Live */
  u_int8_t ipProto;		/* L4 Protocol */
  u_int16_t ipSum;		/* ip header check sum */
  u_int32_t ipSrc;		/* source ip address */
  u_int32_t ipDst;		/* destination ip address */
};




struct rook_ipv6_h
{
  u_int32_t ipFlags;     /* version, traffic class, flow label */
  u_int16_t ipLen;       /* total length */
  u_int8_t ipNH;         /* next header */
  u_int8_t ipHL;         /* hop limit */
  u_int32_t ipSrc[4]; /* source address */
  u_int32_t ipDst[4]; /* dest address */
};


#if (RK_LIL_ENDIAN)
#define GET_IPV6_VERSION(ip6h)       ((htonl(ip6h->ipFlags) & 0xF0000000) >> 28)
#define GET_IPV6_TRAFFIC_CLASS(ip6h) ((htonl(ip6h->ipFlags) & 0x0FF00000) >> 20)
#define GET_IPV6_FLOW_LABEL(ip6h)    ((htonl(ip6h->ipFlags) & 0x000FFFFF))
/*
#define GET_IPV6_VERSION(ip6h)       (ip6h->ipFlags[0] & 0x00FF)
#define GET_IPV6_TRAFFIC_CLASS(ip6h) ((ip6h->ipFlags[0] & 0x00FF) | (ip6h->ipFlags[1] & 0xFF00))
*/
#endif
#if (RK_BIG_ENDIAN)
#define GET_IPV6_VERSION(ip6h)       ((ip6h->ipFlags & 0xF0000000) >> 28)
#define GET_IPV6_TRAFFIC_CLASS(ip6h) ((ip6h->ipFlags & 0x0FF00000) >> 20)
#define GET_IPV6_FLOW_LABEL(ip6h)    ((ip6h->ipFlags & 0x000FFFFF))
/*
#define GET_IPV6_VERSION(htons(ip6h)       (htons(ip6h->ipFlags[0]) & 0x00FF)
#define GET_IPV6_TRAFFIC_CLASS(htons(ip6h) ((htons(ip6h->ipFlags[0]) & 0x00FF) | (htons(ip6h->ipFlags[1]) & 0xFF00))
*/
#endif


struct rook_tcp_h
{
  u_int16_t thSrcPort;
  u_int16_t thDstPort;
  u_int32_t thSeq;
  u_int32_t thAck;
#if (RK_LIL_ENDIAN)
  u_int8_t thX2:4, thOff:4;
#endif
#if (RK_BIG_ENDIAN)
  u_int8_t thOff:4, thX2:4;
#endif
  u_int8_t thFlags;
#ifndef TH_FIN
#define TH_FIN    0x01		/* finished send data */
#endif
#ifndef TH_SYN
#define TH_SYN    0x02		/* synchronize sequence numbers */
#endif
#ifndef TH_RST
#define TH_RST    0x04		/* reset the connection */
#endif
#ifndef TH_PUSH
#define TH_PUSH   0x08		/* push data to the app layer */
#endif
#ifndef TH_ACK
#define TH_ACK    0x10		/* acknowledge */
#endif
#ifndef TH_URG
#define TH_URG    0x20		/* urgent! */
#endif
#ifndef TH_ECE
#define TH_ECE    0x40
#endif
#ifndef TH_CWR
#define TH_CWR    0x80
#endif
#ifndef TH_ALL
#define TH_ALL (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG|TH_ECE|TH_CWR)
#endif
#ifndef TH_STAT 
#define TH_STAT(X) ((X) & (TH_FIN|TH_SYN|TH_RST|TH_ACK))
#endif

  u_int16_t thWin;		/* window */
  u_int16_t thSum;		/* checksum */
  u_int16_t thUrp;		/* urgent pointer */
};



struct rook_udp_h
{
  u_int16_t uhSrcPort;		/* soure port */
  u_int16_t uhDstPort;		/* destination port */
  u_int16_t uhLen;		/* length */
  u_int16_t uhSum;		/* checksum */
};





struct rook_icmpv6_h
{
  u_int8_t icmpType;		/* ICMP type */
#ifndef ICMP6_ECHO
#define ICMP6_ECHO          128
#endif
#ifndef ICMP6_ECHOREPLY
#define ICMP6_ECHOREPLY     129
#endif
#ifndef ICMP6_UNREACH
#define ICMP6_UNREACH       1
#endif
#ifndef ICMP6_PKTTOOBIG
#define ICMP6_PKTTOOBIG     2
#endif
#ifndef ICMP6_TIMXCEED
#define ICMP6_TIMXCEED      3
#endif
#ifndef ICMP6_PARAMPROB
#define ICMP6_PARAMPROB     4
#endif
  u_int8_t icmpCode;		/* ICMP code */
  u_int16_t icmpSum;		/* ICMP Checksum */
  u_int16_t icmpID;		/* ICMP id */
  u_int16_t icmpSeq;		/* ICMP sequence number */
};





struct rook_icmpv4_h
{
  u_int8_t icmpType;
  u_int8_t icmpCode;
  u_int16_t icmpSum;		/* ICMP Checksum */
};


struct rook_icmpv4_d
{
  union
  {
    struct
    {
      u_int16_t id;		/* ICMP id */
      u_int16_t seq;		/* ICMP sequence number */
    } echo;

    // #undef icmp_id
    // #undef icmp_seq
#define icmpID     hun.echo.id
#define icmpSeq    hun.echo.seq

    u_int32_t gateway;		/* gateway host */
    struct
    {
      u_int16_t pad;		/* padding */
      u_int16_t mtu;		/* MTU size */
    } frag;
  } hun;

  union
  {
    struct
    {
      u_int32_t its_otime;
      u_int32_t its_rtime;
      u_int32_t its_ttime;
    } ts;

    struct
    {
      IPv4Hdr idi_ip;
      /* options and then 64 bits of data */
    } ip;
    u_int32_t mask;
    int8_t data[1];
  } dun;
};


struct rook_dns_h
{
  u_int16_t id;
  u_int16_t flag;
#if (RK_LIL_ENDIAN)
#define GET_DNS_QR(X)     ((htons(X) & 0x8000) >> 15)
#define GET_DNS_OPCODE(X) ((htons(X) & 0x7800) >> 11)
#define GET_DNS_AA(X)     ((htons(X) & 0x0400) >> 10)
#define GET_DNS_TC(X)     ((htons(X) & 0x0200) >> 9)
#define GET_DNS_RD(X)     ((htons(X) & 0x0100) >> 8)
#define GET_DNS_RA(X)     ((htons(X) & 0x0080) >> 7)
#define GET_DNS_ZERO(X)   ((htons(X) & 0x0070) >> 4)
#define GET_DNS_RECODE(X) ((htons(X) & 0x000F))
#endif
#if (RK_BIG_ENDIAN)
#define GET_DNS_QR(X)     (((X) & 0x8000) >> 15)
#define GET_DNS_OPCODE(X) (((X) & 0x7800) >> 11)
#define GET_DNS_AA(X)     (((X) & 0x0400) >> 10)
#define GET_DNS_TC(X)     (((X) & 0x0200) >> 9)
#define GET_DNS_RD(X)     (((X) & 0x0100) >> 8)
#define GET_DNS_RA(X)     (((X) & 0x0080) >> 7)
#define GET_DNS_ZERO(X)   (((X) & 0x0020) >> 5)
#define GET_DNS_RECODE(X) (((X) & 0x000F))
#endif

  u_int16_t dataCount[4]; /* 0:question, 1:answer, 2:auth, 3:adds */
};

struct rook_dns_rr_h
{
  u_int16_t type;
  u_int16_t cls;
  u_int32_t ttl;
  u_int16_t len;
};

struct rook_netbios_h
{
  u_int8_t msgType;
  u_int8_t flags;
  u_int16_t len;
};

struct rook_dcerpc_h
{
  u_int8_t majVer;
  u_int8_t minVer;
  u_int8_t pktType;
  u_int8_t pktFlag;
  u_int32_t dataRep;
  u_int16_t fragLen;
  u_int16_t authLen;
  u_int32_t callID;
  u_int16_t maxXmit;
  u_int16_t maxRecv;
  u_int32_t assocGroup;
  u_int8_t ctxNum;
  u_int8_t pad [3];
};

struct rook_ssl_h
{
  u_int16_t ver;
  u_int16_t len;
};

struct rook_tftp_h
{
  u_int16_t op;

  union tftpSeg
  {
    u_int8_t reqName[512]; /* for 1(RRQ), 2(WRQ) */

    struct tftpSegData /* for 3(Data) */
    {
      u_int16_t id;
      u_int8_t payload[512];
    } data;
    
    u_int16_t ackID; /* for 4(Ack) */
    struct tftpSegError
    {
      u_int16_t no;
      u_int8_t msg[512];
    } err;
  } seg;
};

struct rook_template 
{
  int data;
  int proto;
};


#endif /* __PKT_HEADER_H__ */
